﻿//using DWLCLink;
using FPSO.HMI.Utils;
using FPSO.HMI.Views.Dialog;
using FPSO.Models.Constant;
using FPSO.Models.Domain;
using FPSO.Models.ViewModel.Controls;
using FPSO.Services;
using FPSO.Services.Impl;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Opc.Ua;
using OpcUaHelper;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using System.Xml;

namespace FPSO.HMI.Views
{
    /// <summary>
    /// MainView.xaml 的交互逻辑
    /// </summary>
    public partial class MainView : Window
    {
        private TaskManageView taskManageView;
        private ExecuteView cargoExecView;
		private ExecuteView ballastExecView;
		//private ExecuteBallastView ballastExecView;
		private OutAndSwapView outAndSwapView;
        private OPCMonitorView opcMonitorView;
		private OPCTimeLineMonitorView opcTimeLineView;
		private MonitorView monitorView;
        private StatusMonitorView statusMonitorView;
		private UserManageDialog userManageDialog;

		private IDataBindingService bindingService;
        private CommStatusViewModel volumeViewModel;

		private Thread calcThread;
		//记录上一次的船舶监测状态和船舶计算状态
		private ShipDraught m_LastShipRealStatus;
		private ShipCalcState m_LastShipCalcStatus;

		//[DllImport("D:\\PROJECTS_C++\\CiiCalculationDebugExe\\CiiCalculationDll.dll", CallingConvention = CallingConvention.Cdecl)]
		//[DllImport("D:\\NUCAS2008\\DebugExe\\CASISTank.dll", CallingConvention = CallingConvention.Cdecl)]
		//public static extern double qtAccess();
		//[DllImport("DWLCLink.dll", CallingConvention = CallingConvention.Cdecl)]
		//public static extern IntPtr GetHelloMessage();


		//[DllImport("User32.dll")]
		//private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
		public MainView()
        {
			//IntPtr ptr = GetHelloMessage();
			//DWLCLinkCtrl example = new DWLCLinkCtrl();
			//double res = example.qtAccess(1.23, 3.33);
			//double a = 1.23;
			//double b = 3.33;
			//double res1 = DWLCLinkCtrl.qtAccess1(a, b);
			//string a1 = "str1";
			//string a2 = "str2";


			//// 假设返回的是ASCII字符串  
			//try
			//{
			//	// 使用Marshal.PtrToStringAnsi将IntPtr转换为string  
			//	//string message = Marshal.PtrToStringAnsi(ptr);
			//	//Console.WriteLine(message);
			//}
			//finally
			//{
			//	// 注意：如果C++ DLL分配了内存（并且没有使用静态内存或全局变量），  
			//	// 你需要在这里释放它。但是在这个例子中，我们使用静态数组，所以不需要手动释放。  
			//	// 如果需要释放，可能需要在C++ DLL中提供一个释放内存的函数。  
			//}
			//return;

			string output = string.Empty;
			//在系统启动之前先检查运行环境是否满足要求
			bool check = SysEnvironmentCheck();
			if (check == false)
			{
				output = "运行环境检查未通过，即将关闭！";
				System.Windows.MessageBox.Show(output);
				Application.Current.Shutdown();
				return;
			}
			//用户权限检查，可通过g_OnboardPreCheck控制是否需要检查
			if (TankConstant.g_OnboardPreCheck)
			{
				LoginDialog loginDialog = new LoginDialog();
				if (loginDialog.ShowDialog() == false)
				{
					// 退出登录时也退出程序
					Application.Current.Shutdown();
					return;
				}
			}

			try
			{
				if (App.UaClient == null && TankConstant.g_Onboard)
				{
					App.UaClient = new OpcUaClient();
					App.UaClient.ConnectServer(SysConfig.OPCConnStr, SysConfig.OPCBackupConnStr).Wait();
				}
			}
			catch (Exception ex)
			{
				output = "连接Opc服务器失败，即将离线运行！";
				System.Windows.MessageBox.Show(output);
				App.UaClient.Disconnect();
				App.UaClient = null;
				output = string.Empty;
				//return;
			}

			// 默认设为管理员权限
			AuthUtil.SetLoginStatus(1);
			AuthUtil.SetLoginUser("admin");

			InitializeComponent();

            btnClose.Click += (s, e) =>
            {
                var dialgoResult = MessageBox.Show("确定退出系统?", "提示", MessageBoxButton.YesNo);
                if (dialgoResult == MessageBoxResult.Yes)
                {
					if(App.UaClient != null)
					{
						App.UaClient.Disconnect();
						App.UaClient = null;
					}
					Close();
                }
            };

			this.Closing += Window_Closing;

			//在线模式下，获取opc通讯信号
			GetAllOpcTags();
			List<OPCTag> opctaglist = TankConstant.tagList_tankStatus;
			//暂时不启用PDB
			volumeViewModel = new CommStatusViewModel();
			bindingService = new RealDataBindingServiceImpl<CommStatusViewModel>(volumeViewModel);

			if (TankConstant.g_Onboard)
			{
				MainMenu.CargoMonitorBtn.Visibility = Visibility.Visible;
				MainMenu.BallastMonitorBtn.Visibility = Visibility.Visible;
				MainMenu.CargoUnloadMonitorBtn.Visibility = Visibility.Visible;
				MainMenu.TaskManageBtn.Visibility = Visibility.Hidden;
				MainMenu.CommStatusBtn.Visibility = Visibility.Visible;
				MainMenu.OpcMonitorBtn.Visibility = Visibility.Visible;

				cargoExecView = new ExecuteView(1);
				ballastExecView = null;
				outAndSwapView = null;
				taskManageView = null;
				opcMonitorView = null;
				opcTimeLineView = null;
				monitorView = null;
				mainContent.Content = cargoExecView;

				//NOTICE 调试版本把这部分定时刷新的界面功能封掉
				m_LastShipRealStatus = new ShipDraught();
				m_LastShipCalcStatus = new ShipCalcState();
				calcThread = new Thread(CalcTask);
				calcThread.IsBackground = true;
				calcThread.Start();
			}
			else
			{
				MainMenu.CargoMonitorBtn.Visibility = Visibility.Hidden;
				MainMenu.BallastMonitorBtn.Visibility = Visibility.Hidden;
				MainMenu.CargoUnloadMonitorBtn.Visibility = Visibility.Hidden;
				MainMenu.TaskManageBtn.Visibility = Visibility.Visible;
				MainMenu.CommStatusBtn.Visibility = Visibility.Visible;
				MainMenu.OpcMonitorBtn.Visibility = Visibility.Hidden;

				taskManageView = new TaskManageView();
				cargoExecView = null;
				ballastExecView = null;
				outAndSwapView = null;
				opcMonitorView = null;
				opcTimeLineView = null;
				statusMonitorView = null;
				mainContent.Content = taskManageView;
			}

			//根据控件显示，确定各数据的取值范围，如何确定所有获取的数据？
			BarListViewModel viewModel = new BarListViewModel();
			//TaskImpl.GetInstance();
		}

		private void CalcTask()
        {
            while(true)
            {
                try
                {
                    bindingService.ReflushData(DateTime.Now);
                    SafeLoadAlgorithmService algorithmService = SafeLoadAlgorithmService.GetInstance();
                    Dictionary<string, double> levelDic = volumeViewModel.GetTankLevelDic();

					//Dictionary<int, double> fullDic = algorithmService.GetLevelDicByVolumDic(levelDic);
					//Dictionary<int, double> volumDic = volumeViewModel.GetTankVolumDic();
					//Dictionary<int, double> fullDic = algorithmService.GetFullDicByVolumDic(volumDic);
					//ManualCalcResult calcResult = algorithmService.CallManualCalc(fullDic);
					//ManualCalcResult calcResult = algorithmService.CallManualCalc(levelDic,2);
					ManualCalcResult calcResult = null;
					if (calcResult != null)
					{
						//显示数据分为直接显示接收数据和显示计算返回的数据两部分，后者必须要接入safeload后台
						ShipDraught realDraught = volumeViewModel.GetRealDraught();
						ShipDraught calcDraught = calcResult.GetCalcDraught();
						if (cargoExecView != null)
                        {
							cargoExecView.SetShipDraught(calcDraught, realDraught);
							//cargoExecView.SetTankStatus(calcResult);
                        }
						if(ballastExecView != null)
						{
							ballastExecView.SetShipDraught(calcDraught, realDraught);
							//ballastExecView.SetTankStatus(calcResult);
						}
						if (outAndSwapView != null)
                        {
                            outAndSwapView.SetShipDraught(calcDraught, realDraught);
							//outAndSwapView.SetTankStatus(calcResult);  //待测试，这里刷新的是第一个界面？外输&倒舱界面舱室状态也要刷新

							ShipCalcState shipCalcState = calcResult.ShipCalc;
							outAndSwapView.AddStrengthData(shipCalcState.MaxPersf, shipCalcState.MaxPerbm);

							double calc_mid_draft = (calcDraught.MidPDraft + calcDraught.MidSDraft) / 2;
							double real_mid_draft = (realDraught.MidPDraft + realDraught.MidSDraft) / 2;
							outAndSwapView.AddDraftLineData(calc_mid_draft, real_mid_draft);
							outAndSwapView.AddHeelTrimData(Math.Abs(shipCalcState.Heel * 57.3), Math.Abs(shipCalcState.Trim));
							outAndSwapView.AddStabilityData(shipCalcState.GM);
						}

						//这里通过比较的结果，当发生显著变化时向数据库中写入当前装载状态数据
						bool ship_real_sta_equal_check = realDraught.isEqual(m_LastShipRealStatus);
						bool ship_calc_sta_equal_check = calcResult.ShipCalc.isEqual(m_LastShipCalcStatus);
						//bool ship_calc_sta_equal_check = false;
						if (!ship_real_sta_equal_check || !ship_calc_sta_equal_check)
						{
							string realDraught_str = JsonConvert.SerializeObject(realDraught);
							string calcDraught_str = JsonConvert.SerializeObject(calcResult.ShipCalc);
							string tankstatus_str = JsonConvert.SerializeObject(levelDic);

							ShipTankStatusLog logout = new ShipTankStatusLog();
							logout.ShipRealStatus = realDraught_str;
							logout.ShipCalcStatus = calcDraught_str;
							logout.CargoTankStatus = tankstatus_str;
							SysConfig.g_ShipTankStatusLogService.AddShipTankStatusLog(logout);

							//删除当前数据库所有数据，通过计数判断是否需要备份
							if (SysConfig.g_ShipTankStatusLogService.GetDataCount() > 10)
							{
								foreach (ShipTankStatusLog shipTankStatusLog in SysConfig.g_ShipTankStatusLogService.GetAllLogs())
								{
									ShipTankStatusBackupLog shipTankStatusBackupLog = new ShipTankStatusBackupLog();
									shipTankStatusBackupLog.ShipRealStatus = shipTankStatusLog.ShipRealStatus;
									shipTankStatusBackupLog.ShipCalcStatus = shipTankStatusLog.ShipCalcStatus;
									shipTankStatusBackupLog.CargoTankStatus = shipTankStatusLog.CargoTankStatus;
									shipTankStatusBackupLog.LogUpdateTime = shipTankStatusLog.LogUpdateTime;
									SysConfig.g_ShipTankStatusBackupLogService.AddShipTankStatusLog(shipTankStatusBackupLog);
								}
								SysConfig.g_ShipTankStatusLogService.FlushDatas();
							}
							m_LastShipRealStatus = realDraught;
							m_LastShipCalcStatus = calcResult.ShipCalc;
						}
					}
				}
                catch(Exception ex)
                { 
				}
                Thread.Sleep(3000);
            }
        }
		private void GetAllOpcTags()
		{
			if (TankConstant.tagList_tankStatus == null || TankConstant.tagList_tankStatus.Count < 1)
			{
				TankConstant.tagList_tankStatus = GetTagListStatus("./opctag_tankstatus.xml");
				//TankConstant.tagList_tankStatus = GetTagList_TankStatus();
			}

			if (TankConstant.tagList_flammableGasStatus == null || TankConstant.tagList_flammableGasStatus.Count < 1)
			{
				TankConstant.tagList_flammableGasStatus = GetTagListStatus("./opctag_flammablegasstatus.xml");
				//TankConstant.tagList_flammableGasStatus = GetTagList_FlamableGasStatus();
			}

			if (TankConstant.tagList_valveStatus == null || TankConstant.tagList_valveStatus.Count < 1)
			{
				TankConstant.tagList_valveStatus = GetTagListStatus("./opctag_valvestatus.xml");
				//TankConstant.tagList_valveStatus = GetTagList_ValveStatus();
			}

			if (TankConstant.tagList_hardwireStatus == null || TankConstant.tagList_hardwireStatus.Count < 1)
			{
				TankConstant.tagList_hardwireStatus = GetTagListStatus("./opctag_hardwirestatus.xml");
				//TankConstant.tagList_hardwireStatus = GetTagList_HardwireStatus();
			}

			if (TankConstant.tagList_pumpStatus == null || TankConstant.tagList_pumpStatus.Count < 1)
			{
				TankConstant.tagList_pumpStatus = GetTagListStatus("./opctag_pumpstatus.xml");
				//TankConstant.tagList_pumpStatus = GetTagList_PumpStatus();
			}
		}
		private List<OPCTag> GetTagListStatus(string xmlpath)
		{
			List<OPCTag> tagList = new List<OPCTag>();
			try
			{
				XmlDocument xml = new XmlDocument();
				xml.Load(xmlpath);
				XmlNodeList nodeList = xml.SelectNodes("/Tags/Tag");
				foreach (XmlNode node in nodeList)
				{
					string dispName = node.Attributes["DBTag"].Value.Trim();
					string opcTag = node.Attributes["OPCTag"].Value.Trim();
					string opcType = node.Attributes["OpcType"].Value.Trim().ToLower();
					tagList.Add(new OPCTag()
					{
						DispName = dispName,
						OpcName = opcTag,
						OpcType = opcType
					});
				}
			}
			catch (Exception ex)
			{
				CommUtil.AddSystemLog(7, 3, ex.Message);
			}
			return tagList;
		}
		private bool SysEnvironmentCheck()
		{
			if (TankConstant.MyLog == null)
				TankConstant.MyLog = new logs();
			//if (TankConstant.MyDataLog == null)
			//	TankConstant.MyDataLog = new logs(TankConstant.datalogSaveFilePath);

			bool m_safeloadboot = true;
			bool m_mysqlboot = true;
			//暂时封掉部分检查项目
			if (TankConstant.g_OnboardPreCheck)
			{
				string processName = "SafeLoad";
				Process[] processes = Process.GetProcessesByName(processName);
				if (processes.Length == 0)
				{
					try
					{
						Process.Start(SysConfig.SafeLoad_path);
					}
					catch { }
					m_safeloadboot = true;
				}
				else
					m_safeloadboot = true;

				string ConnectionString = ConfigurationManager.AppSettings["MySQLStr"];
				MySqlConnection conn = new MySqlConnection(ConnectionString);
				try
				{
					conn.Open();
					m_mysqlboot = true;
				}
				catch (Exception ex)
				{
					m_mysqlboot = false;
				}
			}

			//bool m_pdbboot = false;
			//PDBConnection conn1 = new PDBConnection(SysConfig.PDBConnStr);
			//try
			//{
			//	conn1.Open();
			//	m_pdbboot = true;
			//}
			//catch (Exception ex)
			//{
			//	m_pdbboot = false;
			//}

			string output = "";
			if (m_safeloadboot == true && m_mysqlboot == true/* && m_pdbboot == true*/)
			{
				output = "系统运行环境配置成功！";
				// 成功就不提示了，加快启动速度
				//System.Windows.MessageBox.Show(output);
				return true;

			}
			else
			{
				if (m_safeloadboot == false)
					output += "配载计算模块加载失败！\r\n";
				if (m_mysqlboot == false)
					output += "MySql数据库加载失败！\r\n";
				//if (m_pdbboot == false)
				//	output += "时序数据库加载失败！\r\n";
				System.Windows.MessageBox.Show(output);
				return false;
			}
		}
		private void UCMenu_OnMenuChanged(int menuPos)
		{
			string contentType = Convert.ToString(mainContent.Content.GetType());
			switch (menuPos)
			{
				case 0:// "货油注入监控":
					if (cargoExecView == null)
					{
						if (TankConstant.g_Onboard)
							cargoExecView = new ExecuteView(1);
						else
							cargoExecView = new ExecuteView(0);
					}
					cargoExecView.ReloadTaskQueue();
					mainContent.Content = cargoExecView;
					break;
				case 1:// "调载":
					if (ballastExecView == null)
					{
						ballastExecView = new ExecuteView(2);
					}
					mainContent.Content = ballastExecView;
					break;
				case 2:// "外输&倒舱":
					if (outAndSwapView == null)
					{
						outAndSwapView = new OutAndSwapView();
					}
					outAndSwapView.ReloadTaskQueue();
					mainContent.Content = outAndSwapView;
					break;
				case 3:// "任务管理":
					if (taskManageView == null)
					{
						taskManageView = new TaskManageView();
					}
					taskManageView.ReloadTaskQueue();
					mainContent.Content = taskManageView;
					break;
				case 4:// "通讯监控":
					if (monitorView == null)
					{
						monitorView = new MonitorView();
					}
					mainContent.Content = monitorView;
					break;
				case 5:// "任务监控":
					if (opcTimeLineView == null)
					{
						opcTimeLineView = new OPCTimeLineMonitorView();
					}
					mainContent.Content = opcTimeLineView;
					break;
				case 6:// "OPC点监控":
					if (opcMonitorView == null)
					{
						opcMonitorView = new OPCMonitorView();
					}
					mainContent.Content = opcMonitorView;
					break;
				case 7:// "用户管理":
					if (userManageDialog == null || !userManageDialog.IsVisible)
					{
						userManageDialog = new UserManageDialog();
						userManageDialog.ShowDialog();
					}
					else
					{
						// 如果窗口已经可见，可以选择将其激活
						userManageDialog.Activate();
					}
					break;
			}
		}
		private void Window_Closing(object sender, CancelEventArgs e)
		{
			if (MessageBox.Show("是否确认退出？", "确认", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
			{
				e.Cancel = false;
				if (App.UaClient != null)
				{
					App.UaClient.Disconnect();
					App.UaClient = null;
				}
			}
			else
			{
				e.Cancel = true;
			}
		}

		private void WindowMove(object sender, MouseEventArgs e)
		{
			if (e.LeftButton == MouseButtonState.Pressed)
			{
				DragMove();
			}
		}
	}
}
